package cn.tannn.ops.quartz.config;

import cn.tannn.ops.quartz.annotation.Job;
import cn.tannn.ops.quartz.annotation.JobMeta;
import cn.tannn.ops.quartz.entity.QrtzClazzMetaEntity;
import cn.tannn.ops.quartz.service.QrtzClazzMetaService;
import cn.tannn.ops.quartz.service.ScheduleService;
import org.reflections.Reflections;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import java.util.Set;

/**
 * 自动注册job
 *
 * @author <a href="https://t.tannn.cn/">tan</a>
 * @version V1.0
 * @date 2024/7/26 上午10:20
 */
@Component
public class AutoRegisterJob implements ApplicationRunner {

    private static final Logger log = LoggerFactory.getLogger(AutoRegisterJob.class);

    private final QrtzClazzMetaService qrtzClazzMetaService;
    private final ScheduleService scheduleService;

    private final QuartzConfig quartzConfig;
    private final ApplicationContext context;

    public AutoRegisterJob(ScheduleService scheduleService
            , QuartzConfig quartzConfig
            , QrtzClazzMetaService qrtzClazzMetaService
            , ApplicationContext context) {
        this.scheduleService = scheduleService;
        this.qrtzClazzMetaService = qrtzClazzMetaService;
        this.quartzConfig = quartzConfig;
        this.context = context;
    }


    @Override
    public void run(ApplicationArguments args) throws Exception {
        String mainClassPath = context.getBeansWithAnnotation(SpringBootApplication.class)
                .values().iterator().next().getClass().getName();
        String packagePath = mainClassPath.substring(0, mainClassPath.lastIndexOf('.'));
        Reflections reflections = new Reflections(packagePath);
        regJobMeta(reflections);
        regJob(reflections);
    }

    /**
     * 注册任务
     * @param reflections Reflections
     */
    private void regJob(Reflections reflections) {
        Set<Class<?>> interfaces = reflections.getTypesAnnotatedWith(Job.class);
        if (interfaces == null || interfaces.isEmpty()) {
            log.info(" no auto register job ");
        }
        for (Class<?> beanClass : interfaces) {
            try {
                Job annotation = beanClass.getAnnotation(Job.class);
                scheduleService.recurringJob((Class<? extends org.quartz.Job>) beanClass, annotation.jobName(), annotation.cron(), annotation.isStartNow());
                log.info(" auto register job success, className {}", beanClass.getName());
            } catch (Exception e) {
                log.warn("auto register job failed, className {}, error message : {}", beanClass.getName(), e.getMessage());
            }
        }
    }

    /**
     * 注册任务元数据
     * @param reflections Reflections
     */
    private void regJobMeta(Reflections reflections) {
        Set<Class<?>> interfaces = reflections.getTypesAnnotatedWith(JobMeta.class);
        if (interfaces == null || interfaces.isEmpty()) {
            log.info(" no auto register job meta ");
        }
        for (Class<?> beanClass : interfaces) {
            try {
                JobMeta annotation = beanClass.getAnnotation(JobMeta.class);
                QrtzClazzMetaEntity meta = new QrtzClazzMetaEntity();
                meta.setClazz(beanClass.getName());
                meta.setName(annotation.name());
                meta.setDescription(annotation.description());
                qrtzClazzMetaService.registerClazzMeta(meta);
                log.info(" auto register job meta success, className {}", beanClass.getName());
            } catch (Exception e) {
                log.error("auto register job meta failed, className {}, error message : {}", beanClass.getName(), e.getMessage());
            }
        }
    }
}
